prefix, 2+2*descsz, value, descsz);
}
+static int print_notes(struct elf_binary *elf, const elf_note *start, const elf_note *end)
+{
+ const elf_note *note;
+ int notes_found = 0;
+
+ for ( note = start; note < end; note = elf_note_next(elf, note) )
+ {
+ if (0 != strcmp(elf_note_name(elf, note), "Xen"))
+ continue;
+
+ notes_found++;
+
+ switch(elf_uval(elf, note, type))
+ {
+ case XEN_ELFNOTE_INFO:
+ print_string_note("INFO", elf , note);
+ break;
+ case XEN_ELFNOTE_ENTRY:
+ print_numeric_note("ENTRY", elf , note);
+ break;
+ case XEN_ELFNOTE_HYPERCALL_PAGE:
+ print_numeric_note("HYPERCALL_PAGE", elf , note);
+ break;
+ case XEN_ELFNOTE_VIRT_BASE:
+ print_numeric_note("VIRT_BASE", elf , note);
+ break;
+ case XEN_ELFNOTE_PADDR_OFFSET:
+ print_numeric_note("PADDR_OFFSET", elf , note);
+ break;
+ case XEN_ELFNOTE_XEN_VERSION:
+ print_string_note("XEN_VERSION", elf , note);
+ break;
+ case XEN_ELFNOTE_GUEST_OS:
+ print_string_note("GUEST_OS", elf , note);
+ break;
+ case XEN_ELFNOTE_GUEST_VERSION:
+ print_string_note("GUEST_VERSION", elf , note);
+ break;
+ case XEN_ELFNOTE_LOADER:
+ print_string_note("LOADER", elf , note);
+ break;
+ case XEN_ELFNOTE_PAE_MODE:
+ print_string_note("PAE_MODE", elf , note);
+ break;
+ case XEN_ELFNOTE_FEATURES:
+ print_string_note("FEATURES", elf , note);
+ break;
+ case XEN_ELFNOTE_HV_START_LOW:
+ print_numeric_note("HV_START_LOW", elf, note);
+ break;
+ default:
+ printf("unknown note type %#x\n",
+ (int)elf_uval(elf, note, type));
+ break;
+ }
+ }
+ return notes_found;
+}
+
int main(int argc, char **argv)
{
const char *f;
struct stat st;
struct elf_binary elf;
const elf_shdr *shdr;
- const elf_note *note, *end;
+ int notes_found = 0;
if (argc != 2)
{
}
elf_set_logfile(&elf, stderr, 0);
- count = elf_shdr_count(&elf);
+ count = elf_phdr_count(&elf);
for ( h=0; h < count; h++)
{
- shdr = elf_shdr_by_index(&elf, h);
- if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE)
+ const elf_phdr *phdr;
+ phdr = elf_phdr_by_index(&elf, h);
+ if (elf_uval(&elf, phdr, p_type) != PT_NOTE)
continue;
- end = elf_section_end(&elf, shdr);
- for (note = elf_section_start(&elf, shdr);
- note < end;
- note = elf_note_next(&elf, note))
+
+ /* Some versions of binutils do not correctly set
+ * p_offset for note segments.
+ */
+ if (elf_uval(&elf, phdr, p_offset) == 0)
+ continue;
+
+ notes_found = print_notes(&elf,
+ elf_segment_start(&elf, phdr),
+ elf_segment_end(&elf, phdr));
+ }
+
+ if ( notes_found == 0 )
+ {
+ count = elf_shdr_count(&elf);
+ for ( h=0; h < count; h++)
{
- if (0 != strcmp(elf_note_name(&elf, note), "Xen"))
+ const elf_shdr *shdr;
+ shdr = elf_shdr_by_index(&elf, h);
+ if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE)
continue;
- switch(elf_uval(&elf, note, type))
- {
- case XEN_ELFNOTE_INFO:
- print_string_note("INFO", &elf , note);
- break;
- case XEN_ELFNOTE_ENTRY:
- print_numeric_note("ENTRY", &elf , note);
- break;
- case XEN_ELFNOTE_HYPERCALL_PAGE:
- print_numeric_note("HYPERCALL_PAGE", &elf , note);
- break;
- case XEN_ELFNOTE_VIRT_BASE:
- print_numeric_note("VIRT_BASE", &elf , note);
- break;
- case XEN_ELFNOTE_PADDR_OFFSET:
- print_numeric_note("PADDR_OFFSET", &elf , note);
- break;
- case XEN_ELFNOTE_XEN_VERSION:
- print_string_note("XEN_VERSION", &elf , note);
- break;
- case XEN_ELFNOTE_GUEST_OS:
- print_string_note("GUEST_OS", &elf , note);
- break;
- case XEN_ELFNOTE_GUEST_VERSION:
- print_string_note("GUEST_VERSION", &elf , note);
- break;
- case XEN_ELFNOTE_LOADER:
- print_string_note("LOADER", &elf , note);
- break;
- case XEN_ELFNOTE_PAE_MODE:
- print_string_note("PAE_MODE", &elf , note);
- break;
- case XEN_ELFNOTE_FEATURES:
- print_string_note("FEATURES", &elf , note);
- break;
- default:
- printf("unknown note type %#x\n",
- (int)elf_uval(&elf, note, type));
- break;
- }
+ notes_found = print_notes(&elf,
+ elf_section_start(&elf, shdr),
+ elf_section_end(&elf, shdr));
+ if ( notes_found )
+ fprintf(stderr, "using notes from SHT_NOTE section\n");
+
}
}
return 0;
}
+static int elf_xen_parse_notes(struct elf_binary *elf,
+ struct elf_dom_parms *parms,
+ const void *start, const void *end)
+{
+ int xen_elfnotes = 0;
+ const elf_note *note;
+
+ parms->elf_note_start = start;
+ parms->elf_note_end = end;
+ for ( note = parms->elf_note_start;
+ (void *)note < parms->elf_note_end;
+ note = elf_note_next(elf, note) )
+ {
+ if ( strcmp(elf_note_name(elf, note), "Xen") )
+ continue;
+ if ( elf_xen_parse_note(elf, parms, note) )
+ return -1;
+ xen_elfnotes++;
+ }
+ return xen_elfnotes;
+}
+
/* ------------------------------------------------------------------------ */
/* __xen_guest section */
int elf_xen_parse(struct elf_binary *elf,
struct elf_dom_parms *parms)
{
- const elf_note *note;
const elf_shdr *shdr;
+ const elf_phdr *phdr;
int xen_elfnotes = 0;
- int i, count;
+ int i, count, rc;
memset(parms, 0, sizeof(*parms));
parms->virt_base = UNSET_ADDR;
parms->virt_hv_start_low = UNSET_ADDR;
parms->elf_paddr_offset = UNSET_ADDR;
- /* find and parse elf notes */
- count = elf_shdr_count(elf);
+ /* Find and parse elf notes. */
+ count = elf_phdr_count(elf);
for ( i = 0; i < count; i++ )
{
- shdr = elf_shdr_by_index(elf, i);
- if ( !strcmp(elf_section_name(elf, shdr), "__xen_guest") )
- parms->guest_info = elf_section_start(elf, shdr);
- if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
+ phdr = elf_phdr_by_index(elf, i);
+ if ( elf_uval(elf, phdr, p_type) != PT_NOTE )
continue;
- parms->elf_note_start = elf_section_start(elf, shdr);
- parms->elf_note_end = elf_section_end(elf, shdr);
- for ( note = parms->elf_note_start;
- (void *)note < parms->elf_note_end;
- note = elf_note_next(elf, note) )
+
+ /*
+ * Some versions of binutils do not correctly set p_offset for
+ * note segments.
+ */
+ if (elf_uval(elf, phdr, p_offset) == 0)
+ continue;
+
+ rc = elf_xen_parse_notes(elf, parms,
+ elf_segment_start(elf, phdr),
+ elf_segment_end(elf, phdr));
+ if ( rc == -1 )
+ return -1;
+
+ xen_elfnotes += rc;
+ }
+
+ /*
+ * Fall back to any SHT_NOTE sections if no valid note segments
+ * were found.
+ */
+ if ( xen_elfnotes == 0 )
+ {
+ count = elf_shdr_count(elf);
+ for ( i = 0; i < count; i++ )
{
- if ( strcmp(elf_note_name(elf, note), "Xen") )
+ shdr = elf_shdr_by_index(elf, i);
+
+ if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
continue;
- if ( elf_xen_parse_note(elf, parms, note) )
+
+ rc = elf_xen_parse_notes(elf, parms,
+ elf_section_start(elf, shdr),
+ elf_section_end(elf, shdr));
+
+ if ( rc == -1 )
return -1;
- xen_elfnotes++;
+
+ if ( xen_elfnotes == 0 && rc > 0 )
+ elf_msg(elf, "%s: using notes from SHT_NOTE section\n", __FUNCTION__);
+
+ xen_elfnotes += rc;
}
+
}
- if ( !xen_elfnotes && parms->guest_info )
+ /*
+ * Finally fall back to the __xen_guest section.
+ */
+ if ( xen_elfnotes == 0 )
{
- parms->elf_note_start = NULL;
- parms->elf_note_end = NULL;
- elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
- parms->guest_info);
- elf_xen_parse_guest_info(elf, parms);
+ count = elf_shdr_count(elf);
+ for ( i = 0; i < count; i++ )
+ {
+ shdr = elf_shdr_by_name(elf, "__xen_guest");
+ if ( shdr )
+ {
+ parms->guest_info = elf_section_start(elf, shdr);
+ parms->elf_note_start = NULL;
+ parms->elf_note_end = NULL;
+ elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
+ parms->guest_info);
+ elf_xen_parse_guest_info(elf, parms);
+ break;
+ }
+ }
}
if ( elf_xen_note_check(elf, parms) != 0 )
+ elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size);
}
+const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr)
+{
+ return elf->image + elf_uval(elf, phdr, p_offset);
+}
+
+const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr)
+{
+ return elf->image
+ + elf_uval(elf, phdr, p_offset) + elf_uval(elf, phdr, p_filesz);
+}
+
const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol)
{
const void *ptr = elf_section_start(elf, elf->sym_tab);
#define __XEN_PUBLIC_ELFNOTE_H__
/*
- * The notes should live in a SHT_NOTE segment and have "Xen" in the
+ * The notes should live in a PT_NOTE segment and have "Xen" in the
* name field.
*
* Numeric types are either 4 or 8 bytes depending on the content of
const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr);
const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr);
+const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr);
+const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr);
+
const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol);
const elf_sym *elf_sym_by_index(struct elf_binary *elf, int index);
unsigned int load_symtab;
unsigned long symtab_addr;
unsigned long symtab_len;
- /*
- * Only one of __elfnote_* or __xen_guest_string will be
- * non-NULL.
- *
- * You should use the xen_elfnote_* accessors below in order to
- * pickup the correct one and retain backwards compatibility.
- */
- const void *__elfnote_section, *__elfnote_section_end;
- const char *__xen_guest_string;
};
extern struct vcpu *idle_vcpu[NR_CPUS];